package com.up.jiasai.modules.oauth.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.up.vms.application.base.abs.BaseController;
import com.up.vms.application.base.auth.UserSession;
import com.up.vms.application.base.exception.SysException;
import com.up.vms.application.base.utils.CryptUtils;
import com.up.vms.application.base.utils.JsonUtils;
import com.up.vms.application.base.utils.RequestUtils;
import com.up.vms.application.base.utils.StringUtils;
import com.up.jiasai.cache.CacheService;
import com.up.jiasai.modules.oauth.jwt.JwtTokenUtil;
import com.up.jiasai.modules.oauth.service.OauthLoginService;
import com.up.jiasai.spring.annotation.LoginAuth;
import com.up.vms.application.common.utils.json.JsonResult;

import com.up.vms.infrastructure.cache.RedisCacheManager;
import com.up.vms.infrastructure.mvc.RespCode;
import com.up.vms.infrastructure.mvc.ReturnCode;
import com.up.vms.infrastructure.util.CommonUtils;
import com.up.vms.interfaces.rest.response.CommonResponse;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 单点登录接口
 */
@Controller
@Slf4j
public class LoginController extends BaseController {
    @Value("${oauth.isTest}")
    private boolean isTest;
    @Value("${oauth.clientId}")
    private String clientId;
    @Value("${oauth.clientSecret}")
    private String clientSecret;
    @Value("${oauth.accessTokenKey}")
    private String accessTokenKey;
    @Value("${soft.domain}")
    private String projectUrl;
    @Value("${oauth.responseType}")
    private String responseType;
    @Value("${yghApp.url}")
    private String yghAppUrl;
    @Value("${server.client.index.url}")
    private String indexUrl;
    @Autowired
    private OauthLoginService oauthLoginService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
//    @Autowired
//    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedisCacheManager redisCacheManager;

    @Autowired
    private CacheService cacheService;
    //测试用openId
    private String openId = "5CF037F14D638CF0BD4A46854624F1D9";

    /**
     * OAuth_firstStep
     * 第三方入口地址，即甬工惠后台应用跳转地址，
     * 甬工惠跳转至此，传递用户tmpToken，
     * 携带OAuth接入的相关参数、tmpToken、以及接收OAuth code的回调地址，重定向至甬工惠(/oauth/authCode)，
     * 甬工惠判断参数正确与否，回调至下方(/callCode)
     */
    @RequestMapping("/oauth/init")
    public void requestServerFirst(HttpServletRequest request, HttpServletResponse response) {
        try {
            String jumpUrl = getStrPar("jumpUrl");

            if (jumpUrl.contains("#")) {
                jumpUrl = jumpUrl.replaceAll("#", "%23");
            }

            log.info("jumpUrl >>> " + jumpUrl);

//            if (CommonUtils.isNotNull(jumpUrl) && jumpUrl.endsWith("Client/cart")) {
//                jumpUrl = jumpUrl.replace("Client/cart", "Client/%23/cart");
//            } else if (CommonUtils.isNotNull(jumpUrl) && jumpUrl.endsWith("Client/user")) {
//                jumpUrl = jumpUrl.replace("Client/user", "Client/%23/user");
//            }


            String redirectUri = projectUrl + "/oauth/callCode";
            String url = yghAppUrl + "/oauth/authCode?responseType=" + responseType + "&clientId=" + clientId + "&redirectUri=" + CryptUtils.urlEncode(redirectUri) + "&jumpUrl=" + CryptUtils.urlEncode(jumpUrl);
            log.debug("跳转URL：\r\n" + CryptUtils.urlDecode(url));
            log.info("跳转URL：\r\n" + url);
            response.sendRedirect(url);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * OAuth_secondStep
     * 接收甬工惠OAuth code回调，
     * 获取OAuth token(/oauth/accessToken),拿到后保存至缓存，有效期默认1天
     * OAuth_thirdStep
     * 使用OAuth code和token 访问甬工惠OAuth用户信息(/oauth/userInfo)
     * 拿到用户信息(openId) loginName等等(甬工惠可配)
     */
    @RequestMapping("/oauth/callCode")
    public void callCode(HttpServletRequest request, HttpServletResponse response) {
        log.debug("queryString:" + request.getQueryString());
        String errorInfo = "";
        try {
            String code = getStrPar("code", "");
            String accessToken = "";
            String redirectUri = indexUrl;
            String jumpUrl = getStrPar("jumpUrl", "");
            if (StringUtils.isNotEmpty(jumpUrl)) {
                log.info("jumpUrl >>>" + jumpUrl);
                redirectUri = jumpUrl;
            }
            if (StringUtils.isEmpty(code)) {
                errorInfo = "获取不到授权,请重新登陆:code=" + request.getQueryString();
                log.error(errorInfo);
                sendHtml(errorInfo);
                return;
            }
            if (isTest) {
                redirectUri = getStrPar("redirectUri");
            } else {
                //获取OAuth accessToken(当前应用的查询数据权限)
                accessToken = redisCacheManager.getRedisTemplate().opsForValue().get(accessTokenKey);
                if (StringUtils.isEmpty(accessToken)) {
                    log.error("当前缓存没有accessToken:[" + accessTokenKey + "]");
                    accessToken = oauthLoginService.getOauthAccessToken();
                    if (StringUtils.isEmpty(accessToken)) {
                        errorInfo = "单点登录系统授权失败";
                        log.warn(errorInfo);
                        super.sendHtml(errorInfo);
                        return;
                    }
                }
                // 获取OAuth 用户信息
                log.info("开始请求用户信息:code=" + code + ",accessToken=" + accessToken);
                openId = oauthLoginService.getOauthUserInfo(code, accessToken);
                if (StringUtils.isEmpty(openId)) {
                    errorInfo = "用户授权失败,获取不到openId";
                    log.error(errorInfo);
                    super.sendHtml(errorInfo);
                    return;
                }
            }
            // 生成JwtToken 重定向
            String token = jwtTokenUtil.createJwtToken(openId);
            //创建跳转URL
            redirectUri = RequestUtils.buildUrl(redirectUri, "accessToken=" + token);
            log.info("登录成功 >>> URL：" + redirectUri);
            response.sendRedirect(redirectUri);
        } catch (SysException e) {
//            e.printStackTrace();
            log.error(e.getErrorInfo());
            CommonResponse commonResponse = new CommonResponse();
            commonResponse.setRespCode(new RespCode("EDI-30101", e.getErrorInfo()));
//            super.sendHtml(e.getErrorInfo());
            super.sendHtml(JSON.toJSONString(commonResponse));
        } catch (Exception e) {
            e.printStackTrace();
//            log.error(e.getMessage(), e);
            log.error("用户授权失败");
            CommonResponse commonResponse = new CommonResponse();
            commonResponse.setRespCode(new RespCode("EDI-30100", "用户授权失败"));
//            super.sendHtml("用户授权失败");
            super.sendHtml(JSON.toJSONString(commonResponse));
        }
    }

    //完全是测试模式,如果上线需要注释掉代码
    @RequestMapping("/oauth/test")
    public void test(HttpServletRequest request, HttpServletResponse response) {
//        if (!isTest) {
//            sendHtml("sorry do not test");
//            return;
//        }
        String redirectUri = getStrPar("redirectUri");
        log.debug("跳转地址>>> " + redirectUri);
        String type = getStrPar("type");
        if (StringUtils.isEmpty(redirectUri)) {
            redirectUri = indexUrl;
        }
        String token = jwtTokenUtil.createJwtToken(openId);
        //保存本地缓存信息
        //用户的唯一标识，系统中唯一且不变
        JSONObject root = new JSONObject();

        String phoneNum = "13616881718";
        String realName = "卢俊";
        String certNbr = "";
        String nickName = "icelove";
        String photo = "";
        String idNumber = "110101199003078275";
        UserSession us = new UserSession();
        us.setId(16L);
        us.setImgurl(photo);
        us.setUserName(realName);
        us.setNickName(nickName);
        us.setRealName(realName);
        us.setLoginTime(new Date());
        us.setPhoneNum(phoneNum);
        try {
            cacheService.putUserSession(openId, us);
            if ("json".equals(type)) {
                JSONObject data = new JSONObject();
                data.put("accessToken", token);
                sendHtml(JsonUtils.toString(new JsonResult("200", "success", data)));
            } else {
                redirectUri = RequestUtils.buildUrl(redirectUri, "accessToken=" + token);
                response.sendRedirect(redirectUri);
            }
        } catch (Exception e) {
            sendHtml("系统出现异常:" + e.getMessage());
            log.error("/oauth/test异常了", e);
        }
    }

    //获取测试模式下的token
    @RequestMapping("/app/getToken")
    public @ResponseBody
    JsonResult getToken(@LoginAuth UserSession session) {
        if (session == null) {
            return new JsonResult("500", "token is error");
        }
        return new JsonResult("200", "token is right");
    }

    @RequestMapping(value = "/app/testToken", method = RequestMethod.GET)
    public void testToken(@RequestParam(value = "openId", required = false) String userOpenId,
                          @RequestParam(value = "redirectUri", required = false) String redirectUri,
                          HttpServletRequest request, HttpServletResponse response) {

        try {
            String queryId = "13214c72e84345ddb6ff8b20377f2b11";
            if (CommonUtils.isNotNull(userOpenId)) {
                queryId = userOpenId;
            }

            String openId = oauthLoginService.testOauth(queryId);

            String token = jwtTokenUtil.createJwtToken(openId);

            if (CommonUtils.isNotNull(redirectUri)) {
                redirectUri = RequestUtils.buildUrl(redirectUri, "accessToken=" + token);
            } else {
                redirectUri = RequestUtils.buildUrl(indexUrl, "accessToken=" + token);
            }
            log.info("登录成功 >>> URL：" + redirectUri);

            response.sendRedirect(redirectUri);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            sendHtml("系统出现异常:" + e.getMessage());
        }
    }
}
